package ca.etsmtl.gti785.classes;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Observable;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import ca.etsmtl.gti785.util.Constants;
import ca.etsmtl.gti785.util.FileTransferJson;
import com.google.gson.Gson;

/**
 * This class contains and stocks the infos of a server. It also sends http request to get the servers infos periodically. 
 * @author Étienne Faucher
 */
public class Server extends Observable 
{
	private String _url;
	private boolean _isOnline;
	private String _name;
	private double _latitude;
	private double _longitude;
	private boolean _isSelected;
	private Fichier _sharedFolder;
	private boolean _hasNotifications;
	private Date _lastAccess;
	
	public Server(String URL)
	{
		_url = URL;
		_name = URL;
		_latitude = -9999;
		_longitude = -9999;
		_sharedFolder = null;
		_hasNotifications = false;
		_lastAccess = new Date();
		GetServerInfos();
		GetFiles();
	}
	
	public String getURL()
	{
		return _url;
	}
	
	public String getName()
	{
		return _name;
	}
	
	public double getLongitude()
	{
		return _longitude;
	}
	
	public double getLatitude()
	{
		return _latitude;
	}
	
	public void SetOnline(boolean isOnline)
	{
		if(_isOnline != isOnline)
		{
			if(isOnline)
			{
				GetServerInfos();
			}
			ServerChanged();
		}
		
		_isOnline = isOnline;
	}
	
	public boolean IsOnline()
	{
		return _isOnline;
	}
	
	public boolean IsSelected()
	{
		return _isSelected;
	}
	
	public void SetSelected(boolean isSelected)
	{
		if(_isSelected != isSelected)
		{
			if(isSelected)
			{
				GetFiles();
			}
			ServerChanged();
		}
		
		_isSelected = isSelected;
	}
	
	public Fichier GetSharedFolder()
	{
		return _sharedFolder;
	}
	
	public Date GetLastAccessDate()
	{
		return _lastAccess;
	}
	
	private void ServerChanged()
	{
		setChanged();
		notifyObservers(this);
	}
	
	public boolean HasNotifications()
	{
		return _hasNotifications;
	}
	
	public void AddNotifications()
	{
		_hasNotifications = true;
		GetFiles();
	}
	
	public void RemoveNotifications()
	{
		_hasNotifications = false;
		ServerChanged();
	}
	
	private void GetServerInfos()
	{
		Thread getInfosThread = new Thread(new Runnable()
		{
			@Override
			public void run() 
			{
				HttpClient httpclient = new DefaultHttpClient();
				try
				{			
		            HttpGet httpget = new HttpGet(_url + Constants.Server_GetInfo);

		            ResponseHandler<String> responseHandler = new BasicResponseHandler();
		            String responseBody = httpclient.execute(httpget, responseHandler);
		            Gson gson = new Gson();
		            Infos serverInfo = gson.fromJson(responseBody, Infos.class);

					_isOnline = true;
		            _name = serverInfo.serverName;
		            _latitude = Double.valueOf(serverInfo.lat);
		            _longitude = Double.valueOf(serverInfo.lon);
					
				}
				catch(Exception e)
				{
					e.printStackTrace();
					_isOnline = false;
				}
				finally
				{
		            httpclient.getConnectionManager().shutdown();
				}
				
				ServerChanged();
			}
		});
		
		getInfosThread.start();
	}
	
	public void GetFiles()
	{
		Thread getFilesThread = new Thread(new Runnable()
		{
			@Override
			public void run() 
			{
				HttpClient httpclient = new DefaultHttpClient();
				try
				{			
		            HttpGet httpget = new HttpGet(_url + Constants.Server_GetFiles);

		            ResponseHandler<String> responseHandler = new BasicResponseHandler();
		            String responseBody = httpclient.execute(httpget, responseHandler);
		            Gson gson = new Gson();
		            Fichier fichiers = gson.fromJson(responseBody, Fichier.class);

					if(fichiers != null)
					{
						_sharedFolder = fichiers;
						_lastAccess = new Date();
					}
				}
				catch(Exception e)
				{
					e.printStackTrace();
				}
				finally
				{
		            httpclient.getConnectionManager().shutdown();
				}
				
				ServerChanged();
			}
		});
		
		getFilesThread.start();
	}
	
	public void SendFiles(final Server serverDestination, final Fichier fileToSend)
	{
		Thread getFilesThread = new Thread(new Runnable()
		{
			@Override
			public void run() 
			{
				HttpClient httpclient = new DefaultHttpClient();
				try
				{	
					FileTransferJson ftjson = new FileTransferJson(serverDestination.getURL() + Constants.Server_TransferFiles, fileToSend); 
					
		            HttpPost httppost = new HttpPost(_url + Constants.Server_TransferFiles);
	                List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1);
	                
	                nameValuePairs.add(new BasicNameValuePair("body", ftjson.toJson()));
	                
	                httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

	                HttpResponse response = httpclient.execute(httppost);
	                StatusLine statusLine = response.getStatusLine();
				    if(statusLine.getStatusCode() == HttpStatus.SC_OK)
				    {
				    	//TODO:Say it's done
				    }
				    else if(statusLine.getStatusCode() == HttpStatus.SC_REQUEST_TIMEOUT)
				    {
				    	//TODO:Say it's too big
				    }
				    else
				    {
				    	//TODO:Say it can't transfer the file
				    	response.getEntity().getContent().close();
				    }
				}
				catch(Exception e)
				{
					e.printStackTrace();
				}
				finally
				{
		            httpclient.getConnectionManager().shutdown();
				}
			}
		});
		
		getFilesThread.start();
	}
}
